package com.client;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.Query;
import com.google.gwt.visualization.client.QueryResponse;
import com.google.gwt.visualization.client.Query.Callback;

public class PLSearch extends SlidePanel {
	public DecoratorPanel dplSearch;
	public FlexTable ftSearch;
	public TagsPanel tpTags;
	public HTML hSearchHint;
	public Button btnSearch;
	public DisclosurePanel plAdv;
	public FlexTable gAdvSearch;
	public PagedTagsPanel ptpTags;
	public HorizontalPanel hpNavi;
	public Button btnPrev;
	public Button btnNext;
	public TextBox tbTag;
	public Button btnReset;
	public DateBox dbBegin = null;
	public DateBox dbEnd = null;
	public DateFormatter dfmt = null;
	public AxisPanel apX = null;
	public AxisPanel apY = null;

	private int pageSize = 15;

	protected void onFirstShow() {
		this.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		this.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

		dplSearch = new DecoratorPanel();
		ftSearch = new FlexTable();
		ftSearch.setStyleName("appSearchTable");

		tpTags = new TagsPanel(pageSize, 1, new ClkRemoveTag());
		tpTags.setStyleName("appTagSelected");
		hSearchHint = new HTML(CNStatsFront.get().constants.searchHint());
		tpTags.insert(hSearchHint, 0);
		btnSearch = new Button(CNStatsFront.get().constants.search(),
				new ClkSearch());

		ptpTags = new PagedTagsPanel(pageSize);
		ptpTags.setStyleName("appTagList");
		hpNavi = new HorizontalPanel();
		hpNavi.setStyleName("appNavi");
		hpNavi.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
		hpNavi.setSpacing(2);
		btnPrev = new Button();
		btnNext = new Button();
		btnPrev.setText("<");
		btnNext.setText(">");
		btnPrev.addClickHandler(new ClkNav("prev"));
		btnNext.addClickHandler(new ClkNav("next"));
		btnPrev.setEnabled(false);
		btnNext.setEnabled(false);
		tbTag = new TextBox();
		tbTag.setStyleName("appTagSearch");
		tbTag.addFocusHandler(new FocusHandler() {
			public void onFocus(FocusEvent event) {
				tbTag.setText("");
			}
		});
		tbTag.addBlurHandler(new BlurHandler() {
			public void onBlur(BlurEvent event) {
				tbTag.setText(CNStatsFront.get().constants.searchTag());
			}
		});
		tbTag.addKeyPressHandler(new KeyPressHandler() {
			public void onKeyPress(KeyPressEvent event) {
				// Get return key
				if (tbTag.getText().length() > 0 && 13 == event.getCharCode()) {
					CNStatsFront.get().plSearch.hSearchHint.setVisible(false);
					CNStatsFront.get().plSearch.addTag(tbTag.getText());
					CNStatsFront.get().plSearch.ptpTags.showTags(
							CNStatsFront.get().plSearch.tpTags.getTagsText(), "next");
					tbTag.setText("");
					tbTag.setFocus(true);
				}
			}
		});
		tbTag.setText(CNStatsFront.get().constants.searchTag());
		btnReset = new Button(CNStatsFront.get().constants.reset(), new ClkReset());

		hpNavi.add(btnPrev);
		hpNavi.add(btnNext);
		hpNavi.add(tbTag);
		hpNavi.add(btnReset);

		plAdv = new DisclosurePanel(CNStatsFront.get().constants.advanced());
		plAdv.addOpenHandler(new OpenHandlerAdv());

		this.add(dplSearch);
		dplSearch.add(ftSearch);
		ftSearch.setWidget(0, 0, tpTags);
		ftSearch.setWidget(0, 1, btnSearch);
		ftSearch.getFlexCellFormatter().setHorizontalAlignment(0, 1,
				HasHorizontalAlignment.ALIGN_RIGHT);
		ftSearch.getFlexCellFormatter().setColSpan(1, 0, 2);
		ftSearch.setWidget(1, 0, ptpTags);
		ftSearch.getFlexCellFormatter().setColSpan(2, 0, 2);
		ftSearch.setWidget(2, 0, hpNavi);
		ftSearch.getFlexCellFormatter().setColSpan(3, 0, 2);
		ftSearch.setWidget(3, 0, plAdv);
		ftSearch.getCellFormatter().addStyleName(1, 0, "appTags");
		this.reset();

		// Query.create(CNStatsFront.baseURL + "queryhistory").send(
		// new CBQueryHistory());
	}

	public void showAdvSearch() {
		if (null == this.plAdv.getContent()) {
			CNStatsFront.get().showLoading(true);
			this.gAdvSearch = new FlexTable();
			this.dbBegin = new DateBox();
			this.dbEnd = new DateBox();
			this.dfmt = new DateFormatter();
			this.apX = new AxisPanel();
			this.apY = new AxisPanel();
			
			this.gAdvSearch.setHTML(0, 0, CNStatsFront.get().constants.begin());
			this.gAdvSearch.setWidget(0, 1, this.dbBegin);
			this.gAdvSearch.setHTML(1, 0, CNStatsFront.get().constants.end());
			this.gAdvSearch.setWidget(1, 1, this.dbEnd);
			this.gAdvSearch.setHTML(2, 0, CNStatsFront.get().constants.format());
			this.gAdvSearch.setWidget(2, 1, this.dfmt);
			this.gAdvSearch.setHTML(3, 0, CNStatsFront.get().constants.x());
			this.gAdvSearch.setWidget(3, 1, this.apX);
			this.gAdvSearch.setHTML(4, 0, CNStatsFront.get().constants.y());
			this.gAdvSearch.setWidget(4, 1, this.apY);

			this.gAdvSearch.getCellFormatter().setHorizontalAlignment(0, 0,
					HasHorizontalAlignment.ALIGN_RIGHT);
			this.gAdvSearch.getCellFormatter().setHorizontalAlignment(1, 0,
					HasHorizontalAlignment.ALIGN_RIGHT);
			this.gAdvSearch.getCellFormatter().setHorizontalAlignment(2, 0,
					HasHorizontalAlignment.ALIGN_RIGHT);
			this.gAdvSearch.getCellFormatter().setHorizontalAlignment(3, 0,
					HasHorizontalAlignment.ALIGN_RIGHT);
			this.gAdvSearch.getCellFormatter().setHorizontalAlignment(4, 0,
					HasHorizontalAlignment.ALIGN_RIGHT);

			this.plAdv.setStyleName("appAdvSearch");
			this.gAdvSearch.setStyleName("appAdvSearchTable");

			this.gAdvSearch.getColumnFormatter().setWidth(1, "80%");
			this.dbBegin.setWidth("100%");
			this.dbEnd.setWidth("100%");
			this.dfmt.setWidth("100%");
//			this.apX.setWidth("100%");
//			this.apY.setWidth("100%");

			this.apX.setPair(this.apY);
			this.apY.setPair(this.apX);
			
			this.plAdv.setContent(this.gAdvSearch);
			this.plAdv.setAnimationEnabled(true);
			this.apY.cbOnlyDate.setValue(true, true);
			this.apX.cbOnlyDate.setValue(true, true);
			for(int i=1;i<=this.pageSize;i++) {
				Tag tag = (Tag)this.tpTags.getWidget(i);
				if (true == tag.isVisible())
					this.apY.tpTags.addTag(tag.getText());
			}
			CNStatsFront.get().showLoading(false);
		}
	}

	public void reset() {
		tpTags.clearTags();
		hSearchHint.setVisible(true);
		plAdv.setOpen(false);

		ptpTags.reset();

		if (null != CNStatsFront.get().plSearch.plAdv.getContent()) {
			this.dbBegin.setValue(null);
			this.dbEnd.setValue(null);
			this.dfmt.reset();
			this.apX.reset(true);
			this.apY.reset(false);
		}
	}

	public int getPageSize() {
		return pageSize;
	}
	
	public void addTag(String tag) {
		this.tpTags.addTag(tag);
		if (null!= this.apY &&
				false == this.apY.cbOnlyDate.getValue()) {
			this.apY.tpTags.addTag(tag);
		}
		else if (null!= this.apX &&
				false == this.apX.cbOnlyDate.getValue()) {
			this.apX.tpTags.addTag(tag);
		}
	}
	
	public void removeTag(Tag tag) {
		this.tpTags.removeTag(tag);
		if (null!= this.apY &&
				false == this.apY.cbOnlyDate.getValue()) {
			for (int i=0;i<this.pageSize;i++) {
				Tag t = (Tag) this.apY.tpTags.getWidget(i);
				if (true == tag.getText().equals(t.getText())) {
					this.apY.tpTags.removeTag(t);
					return;
				}
			}					
		}
		else if (null!= this.apX &&
				false == this.apX.cbOnlyDate.getValue()) {
			for (int i=0;i<this.pageSize;i++) {
				Tag t = (Tag) this.apX.tpTags.getWidget(i);
				if (true == tag.getText().equals(t.getText())) {
					this.apX.tpTags.removeTag(t);
					return;
				}
			}
		}
	}
}

final class OpenHandlerAdv implements OpenHandler<DisclosurePanel> {
	public void onOpen(OpenEvent<DisclosurePanel> event) {
		CNStatsFront.get().plSearch.showAdvSearch();
	}
}

final class ClkSearch implements ClickHandler {
	public void onClick(ClickEvent event) {
		String tags = CNStatsFront.get().plSearch.tpTags.getTagsText();
		if (tags.equals(""))
			return;
		String searchURL = CNStatsFront.baseURL + "querystats?tags="
				+ CNStatsFront.get().plSearch.tpTags.getTagsText();

		DateTimeFormat dfmt = DateTimeFormat.getFormat("yyyyMMddHHmmss");
		if (null != CNStatsFront.get().plSearch.dbBegin
				&& null != CNStatsFront.get().plSearch.dbBegin.getValue()) {
			searchURL += "&begin="
					+ dfmt.format(CNStatsFront.get().plSearch.dbBegin.getValue());
		}
		if (null != CNStatsFront.get().plSearch.dbEnd
				&& null != CNStatsFront.get().plSearch.dbEnd.getValue()) {
			searchURL += "&end="
					+ dfmt.format(CNStatsFront.get().plSearch.dbEnd.getValue());
		}
		if (null != CNStatsFront.get().plSearch.dfmt) {
			searchURL += "&dfmt=" + CNStatsFront.get().plSearch.dfmt.getDateFormat();
		}
		if (null != CNStatsFront.get().plSearch.apX
				&& CNStatsFront.get().plSearch.apX.getAxis().length() > 0) {
			searchURL += "&x=" + CNStatsFront.get().plSearch.apX.getAxis();
		}
		if (null != CNStatsFront.get().plSearch.apY
				&& CNStatsFront.get().plSearch.apY.getAxis().length() > 0) {
			searchURL += "&y=" + CNStatsFront.get().plSearch.apY.getAxis();
		}

		CNStatsFront.get().showLoading(true);
		Query.create(URL.encode(searchURL)).send(new CBQueryStats());
	}
}

final class CBQueryStats implements Callback {
	public void onResponse(QueryResponse response) {
		CNStatsFront.get().showLoading(false);
		if (response.isError()) {
			CNStatsFront.get().showInfo(
					response.getMessage() + ":" + response.getDetailedMessage());
		} else {
			// Get the data from the QueryResponse.
			DataTable data = response.getDataTable();
			CNStatsFront.get().plCharts.setData(data);
			CNStatsFront.get().plCharts.show();
			CNStatsFront.get().plCharts.draw();
		}
	}
}

// final class CBQueryHistory implements Callback {
// public void onResponse(QueryResponse response) {
// if (response.isError()) {
// // TODO: Don't need pop up message.
// return;
// } else {
// DataTable data = response.getDataTable();
//
// MultiWordSuggestOracle oracle = (MultiWordSuggestOracle) CNStatsFront
// .get().plSearch.sbTags.getSuggestOracle();
// for (int i = 0; i < data.getNumberOfRows(); i++) {
// oracle.add(data.getValueString(i, 0));
// }
// }
// }
// }

final class ClkNav implements ClickHandler {
	private String direction;

	public ClkNav(String direction) {
		super();
		this.direction = direction;
	}

	public void onClick(ClickEvent event) {
		if (this.direction.equals("next"))
			CNStatsFront.get().plSearch.ptpTags.next();
		else if (this.direction.equals("prev"))
			CNStatsFront.get().plSearch.ptpTags.prev();
	}
}

final class ClkReset implements ClickHandler {
	public void onClick(ClickEvent event) {
		CNStatsFront.get().plSearch.reset();
	}
}

final class ClkRemoveTag implements ClickHandler {
	public void onClick(ClickEvent event) {
		CNStatsFront.get().plSearch.removeTag((Tag) event.getSource());
		if (0 == CNStatsFront.get().plSearch.tpTags.getTagAmount())
			CNStatsFront.get().plSearch.hSearchHint.setVisible(true);
		CNStatsFront.get().plSearch.ptpTags.showTags(
				CNStatsFront.get().plSearch.tpTags.getTagsText(), "next");
	}
}
